package com.qsw.crashcollectionlib.core;

import com.qsw.crashcollectionlib.bean.ExceptionMessage;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class ExceptionTask {
    private static final String TAG = "ExceptionTask";
    private static final int TASK_SIZE_DANGER = 300;// 任务池中的报警数量
    private static final int TASK_DANGER_TIMESTAMP_INTERVAL = 30 * 1000;// 任务池报警信息最小间隔时间
    private static final int TASK_SIZE_TIMESTAMP_INTERVAL = 5 * 1000;// 任务池数量信息最小间隔时间

    private static ExceptionTask mExceptionTask;

    /**
     * 日志文件控制类
     */
    private LogFileController mLogFileController;

    /**
     * 任务线程池
     */
    private LinkedBlockingQueue<ExceptionMessage> mTaskQueue;// 任务队列

    private boolean mNeedRun = true;
    private long mLastSizeTimestamp = -1;
    private long mLastDangerTimestamp = -1;

    private int mTaskDangerSize = TASK_SIZE_DANGER;
    private OnTaskSizeDangerListener mOnTaskSizeDangerListener;

    private ExceptionTask() {
        mLogFileController = new LogFileController();

        mTaskQueue = new LinkedBlockingQueue<>();
        mTaskThread.start();
    }

    public static ExceptionTask getInstance() {
        if (mExceptionTask == null) {
            synchronized (ExceptionTask.class) {
                if (mExceptionTask == null) {
                    mExceptionTask = new ExceptionTask();
                }
            }
        }
        return mExceptionTask;
    }

    /**
     * 保存异常到日志文件
     *
     * @param em 要保存的异常
     */
    public void saveException2Log(final ExceptionMessage em) {
        mTaskQueue.offer(em);
    }

    /**
     * 停止接收数据
     */
    public void shotdown() {
        mNeedRun = false;
        if (mTaskThread.isAlive() && !mTaskThread.isInterrupted()) {
            mTaskThread.interrupt();
        }
    }

    /**
     * 设置线程池报警阈值
     *
     * @param taskDangerSize 线程池报警阈值
     */
    public void setTaskDangerSize(int taskDangerSize) {
        this.mTaskDangerSize = taskDangerSize;
    }

    /**
     * 任务处理线程
     */
    private final Thread mTaskThread = new Thread() {
        @Override
        public void run() {
            while (mNeedRun) {
                try {
                    ExceptionMessage exceptionMessage = mTaskQueue.take();
                    if (exceptionMessage.getLogPath() == null) {
                        exceptionMessage.setLogPath(CrashExceptionProcesser.getDefaultLogPath());
                    }
                    if (exceptionMessage.getLogName() == null) {
                        exceptionMessage.setLogName(CrashExceptionProcesser.getDefaultLogName());
                    }
                    mLogFileController.saveException2Log(exceptionMessage);

                    if (System.currentTimeMillis() - mLastSizeTimestamp > TASK_SIZE_TIMESTAMP_INTERVAL) {
                        if (mTaskQueue.size() > mTaskDangerSize) {
                            if (System.currentTimeMillis() - mLastDangerTimestamp < TASK_DANGER_TIMESTAMP_INTERVAL) {
                                continue;
                            }
                            mLastSizeTimestamp = System.currentTimeMillis();
                            mLastDangerTimestamp = mLastSizeTimestamp;
                            if (mOnTaskSizeDangerListener != null) {
                                mOnTaskSizeDangerListener.onTaskSizeDanger(true, mTaskQueue.size());
                            }
                        } else {
                            if (mLastDangerTimestamp < 0) {
                                continue;
                            }
                            mLastSizeTimestamp = System.currentTimeMillis();
                            mLastDangerTimestamp = -1;
                            if (mOnTaskSizeDangerListener != null) {
                                mOnTaskSizeDangerListener.onTaskSizeDanger(false, mTaskQueue.size());
                            }
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    /**
     * 设置当任务池中的任务数量过多可能导致内存风险时的回调
     *
     * @param onTaskSizeDangerListener 当任务池中的任务数量过多可能导致内存风险时的回调
     */
    public void setOnTaskSizeDangerListener(OnTaskSizeDangerListener onTaskSizeDangerListener) {
        mOnTaskSizeDangerListener = onTaskSizeDangerListener;
    }

    /**
     * 当任务池中的任务数量过多可能导致内存风险时的回调
     */
    public interface OnTaskSizeDangerListener {
        /**
         * 任务数过多导致内存风险
         *
         * @param danger true：危险；false：安全
         * @param size   当前数量
         */
        void onTaskSizeDanger(boolean danger, int size);
    }
}
